﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using OpenTK;
using OpenTK.Graphics.OpenGL;
using OpenTK.Graphics;
using Watcher.Logic;
using Watcher.Data;
using Apache.NMS;
using System.Collections;
using Apache.NMS.ActiveMQ;


namespace Watcher
{
    public partial class MainWindow : Form
    {


        private static IConnection _connection;
        private static ISession _session;
        private static IDestination _destination;
        private static IQueueBrowser _browser;
        private static IConnectionFactory _factory;
        private static ArrayList _messagequeue = new ArrayList();

        static float angle = 0.0f;
        static bool run = false;
        static bool serverselected = false;
        static Globals _globals = Globals.getInstance();
        public MainWindow()
        {
            InitializeComponent();
            if (_globals.MessageQueueServer == null)
            {
                Servername.Text = "No server selected";
                serverselected = false;
            }
            FlightStart.Enabled = false;
            
        }

        #region Events

        Vector3d[] vertices = new Vector3d[1000];
        List<Vector3d> vert = new List<Vector3d>();
        int zoom = 5;
        double x = -2f;
        double y = 0.0;
        double incr = 0.001;

        private void redButton_Click(object sender, EventArgs e)
        {
            GL.ClearColor(Color.Gray);
            glControl1.Invalidate();
        }

        private void greenButton_Click(object sender, EventArgs e)
        {
            GL.ClearColor(Color.White);
            glControl1.Invalidate();
        }

        private void StopFlightButton_Click(object sender, EventArgs e)
        {
            run = false;
            vert.RemoveRange(0, vert.Count);
            x = 0f;
            y = 0f;
            
        }

        private void glControl1_Paint(object sender, PaintEventArgs e)
        {
            glControl1.MakeCurrent();

            GL.Clear(ClearBufferMask.ColorBufferBit);
            glControl1.SwapBuffers();
        }

        private void glControl1_Resize(object sender, EventArgs e)
        {
            if (glControl1.ClientSize.Height == 0)
                glControl1.ClientSize = new System.Drawing.Size(glControl1.ClientSize.Width, 1);

            GL.Viewport(0, 0, glControl1.ClientSize.Width, glControl1.ClientSize.Height);
        }

        private void glControl1_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyData)
            {
                case Keys.Escape:
                    this.Close();
                    break;
            }
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            glControl1.KeyDown += new KeyEventHandler(glControl_KeyDown);
            glControl1.KeyUp += new KeyEventHandler(glControl_KeyUp);
            glControl1.Resize += new EventHandler(glControl_Resize);
            glControl1.Paint += new PaintEventHandler(glControl_Paint);

            Text = "Birdwatcher v0.1 Alpha " +
                GL.GetString(StringName.Vendor) + " " +
                GL.GetString(StringName.Renderer) + " " +
                GL.GetString(StringName.Version);

            GL.ClearColor(Color.Black);
            GL.Enable(EnableCap.DepthTest);

            Application.Idle += Application_Idle;

            // Ensure that the viewport and projection matrix are set correctly.
            glControl_Resize(glControl1, EventArgs.Empty);



        }

        void glControl_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Alt)
                zoom += 1;
        }

        #endregion

        #region OnClosing

        protected override void OnClosing(CancelEventArgs e)
        {
            Application.Idle -= Application_Idle;

            base.OnClosing(e);
        }

        #endregion

        #region Application_Idle event

        void Application_Idle(object sender, EventArgs e)
        {
            while (glControl1.IsIdle)
            {
                Render();
            }
        }

        #endregion

        #region glControl.Resize event handler

        void glControl_Resize(object sender, EventArgs e)
        {
            OpenTK.GLControl c = sender as OpenTK.GLControl;

            if (c.ClientSize.Height == 0)
                c.ClientSize = new System.Drawing.Size(c.ClientSize.Width, 1);

            GL.Viewport(0, 0, c.ClientSize.Width, c.ClientSize.Height);

            float aspect_ratio = Width / (float)Height;
            Matrix4 perpective = Matrix4.CreatePerspectiveFieldOfView(MathHelper.PiOver4, aspect_ratio, 1, 64);
            GL.MatrixMode(MatrixMode.Projection);
            GL.LoadMatrix(ref perpective);
        }

        #endregion

        #region glControl1.KeyDown event handler
         
        void glControl_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyData)
            {
                case Keys.Escape:
                    //this.Close();
                    break;
                case Keys.LShiftKey:
                    if (zoom > 5)
                    {
                        zoom -= 1;
                    }
                    break;
                case Keys.RShiftKey:
                    if (zoom < 50)
                    {
                        zoom += 1;
                    }
                    break;
            }
        }

        #endregion

        #region glControl1.Paint event handler

        void glControl_Paint(object sender, PaintEventArgs e)
        {
            Render();
        }

        #endregion

        #region private void Render()

        private void Render()
        {
            Matrix4 lookat = Matrix4.LookAt(0,0,30+zoom, 0, 0, 0, 0, 1, 0);
            GL.MatrixMode(MatrixMode.Modelview);
            GL.LoadMatrix(ref lookat);

            //GL.Rotate(angle, 0.0f, 1.0f, 0.0f);
            //angle += 0.5f;

            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

            //DrawCube();
            if (run)
            {
                DrawGraph();
                RetrieveMessages();
            }
            DrawAxis();
            Validate();
            glControl1.SwapBuffers();
            //glControl2.SwapBuffers();
        }

        public void Validate()
        {
            if (vert.Count < 1)
            {
                StopFlight.Enabled = false;
            }
            else
            {
                StopFlight.Enabled = true;
            }

            if (_globals.MessageQueueServer != null)
            {
                serverselected = true;
                ServerAddress.Text = _globals.MessageQueueServer.Ip;
                ServerPort.Text = _globals.MessageQueueServer.Port;
                Servername.Text = _globals.MessageQueueServer.Name;
                
            }


            if (serverselected)
            {
                FlightStart.Enabled = true;
            }
            else
            {
                FlightStart.Enabled = false;
            }

        }

        #endregion

        #region private void DrawCube()

        private void DrawAxis()
        {
            GL.Begin(BeginMode.LineStrip);
            GL.LineStipple(2, (short)1);
            GL.Color3(Color.DarkSlateGray);
            GL.Vertex2(-glControl1.Width, 0);
            GL.Vertex2(glControl1.Width, 0);
            GL.Vertex2((float)0 - zoom, (float)glControl1.Height);
            GL.Vertex2((float)0 - zoom, (float)-glControl1.Height);
            GL.End();
        }

        private void DrawGraph()
        {
            GL.Begin(BeginMode.LineStrip);
            y = Math.Pow(Math.PI,2) * x * Math.Sin(x * Math.Pow(Math.PI, 1/2));
            x = x + incr;
            xbox.Text = x.ToString();
            ybox.Text = y.ToString();
            zbox.Text = 2.ToString(); 
            vert.Add(new Vector3d(x-zoom, y, 2));
            if (vert.Count > Width * 10)
            {
                vert.RemoveAt(1);
            }
            foreach (Vector3d vertex in vert)
            {
                GL.Color3(Math.Abs(vertex.Y), 2.0f - (Math.Abs(vertex.Y) - (Math.Abs(vertex.Y) / 9)), 0);
                GL.Vertex3(vertex.X, vertex.Y, vertex.Z);
           
            }
           
            GL.End();
        }

        private void DrawAcceleration()
        {
            GL.Begin(BeginMode.LineStrip);
            if (vert.Count > Width * 10)
            {
                vert.RemoveAt(1);
            }
            foreach (Vector3d vertex in vert)
            {
                GL.Color3(Math.Abs(vertex.Y), 2.0f - (Math.Abs(vertex.Y) - (Math.Abs(vertex.Y) / 9)), 0);
                GL.Vertex3(vertex.X, vertex.Y, vertex.Z);

            }
            GL.End();
        }

        private void DrawCube()
        {
            GL.Begin(BeginMode.Quads);
            GL.Rotate(10, 1.0f, 1.0f, 1.0f);
            
            GL.Color3(Color.Blue);
            GL.Vertex3(-1.0f, -1.0f, -1.0f);
            GL.Vertex3(-1.0f, 1.0f, -1.0f);
            GL.Vertex3(1.0f, 1.0f, -1.0f);
            GL.Vertex3(1.0f, -1.0f, -1.0f);

            GL.Color3(Color.Yellow);
            GL.Vertex3(-1.0f, -1.0f, -1.0f);
            GL.Vertex3(1.0f, -1.0f, -1.0f);
            GL.Vertex3(1.0f, -1.0f, 1.0f);
            GL.Vertex3(-1.0f, -1.0f, 1.0f);

            GL.Color3(Color.Red);

            GL.Vertex3(-1.0f, -1.0f, -1.0f);
            GL.Vertex3(-1.0f, -1.0f, 1.0f);
            GL.Vertex3(-1.0f, 1.0f, 1.0f);
            GL.Vertex3(-1.0f, 1.0f, -1.0f);

            GL.Color3(Color.Orange);
            GL.Vertex3(-1.0f, -1.0f, 1.0f);
            GL.Vertex3(1.0f, -1.0f, 1.0f);
            GL.Vertex3(1.0f, 1.0f, 1.0f);
            GL.Vertex3(-1.0f, 1.0f, 1.0f);

            GL.Color3(Color.Violet);
            GL.Vertex3(-1.0f, 1.0f, -1.0f);
            GL.Vertex3(-1.0f, 1.0f, 1.0f);
            GL.Vertex3(1.0f, 1.0f, 1.0f);
            GL.Vertex3(1.0f, 1.0f, -1.0f);

            GL.Color3(Color.ForestGreen);
            GL.Vertex3(1.0f, -1.0f, -1.0f);
            GL.Vertex3(1.0f, 1.0f, -1.0f);
            GL.Vertex3(1.0f, 1.0f, 1.0f);
            GL.Vertex3(1.0f, -1.0f, 1.0f);

            GL.End();
        }

        #endregion

        private void ServerAddress_onvaluechanged(object sender, EventArgs e)
        {
            if (ServerAddress.Text != null)
            {
                serverselected = true;
            }
            else
            {
                serverselected = false;
            }
        }


        private void newToolStripMenuItem_Click(object sender, EventArgs e)
        {
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AboutBox1 ab = new AboutBox1();
            ab.Show();
            ab.Text = "About Birdwatcher"; 
        }

        private void selectServerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Servers s = new Servers();
            s.Show();
            s.Text = "Serverlist";
        }

        private void FlightStart_Click(object sender, EventArgs e)
        {
            run = true;
            MakeConnection();
        }

        private void addServerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AddServer s = new AddServer();
            s.Show();
        }

        public void MakeConnection()
        {

            string brokerUri = "tcp://" + _globals.MessageQueueServer.Ip + ":" + _globals.MessageQueueServer.Port + "/";
            string queue = "parameters";
            _factory = new ConnectionFactory(brokerUri);
            _connection = _factory.CreateConnection();
            _connection.Start();
            _session = _connection.CreateSession();
            _destination = _session.GetQueue(queue);
            _browser = _session.CreateBrowser((IQueue)_destination);
        }

        public void RetrieveMessages()
        {
            IEnumerator enumeration = _browser.GetEnumerator();
            ArrayList values = new ArrayList();
            // Logger log = Logger.getInstance();
            while (enumeration.MoveNext())
            {
                IMessage message = (IMessage)enumeration.Current;
                values = (ArrayList)message.Properties.Values;
                _messagequeue.Add(values);
                Console.WriteLine("Value written: " + values[0].ToString() + "#" + values[values.Count - (values.Count - 3)].ToString());
                //log.WriteToFile();
            }
            //log.Close();
        }

        #region public static void Main()

        ///// <summary>
        ///// Entry point of this example.
        ///// </summary>
        //[STAThread]
        //public static void Main()
        //{
        //    using (SimpleForm example = new SimpleForm())
        //    {
        //        Utilities.SetWindowTitle(example);
        //        example.ShowDialog();
        //    }
        //}

        #endregion

    }
}
